package com.wh.basic.jwt;

import com.sun.xml.bind.v2.runtime.output.SAXOutput;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

/**
 * RSA工具类   负责对RSA密钥的创建、读取功能(公钥和私钥)
 */
public class RsaUtils {

    /**
     * 密钥大小
     */
    private static final int DEFAULT_KEY_SIZE = 2048;  // 生成的大小

    /**
     * 从文件中读取公钥
     *

     * @return 公钥对象
     * @throws Exception
     *//*
    public static PublicKey getPublicKey(String filePath) throws Exception {
        byte[] bytes = readFile(filePath);
        return getPublicKey(bytes);
    }*/

    public static PublicKey getPublicKey(InputStream inputStream) throws Exception {
        // 从InputStream读取PEM格式的公钥文件内容
        byte[] keyBytes = readAllBytes(inputStream);

        // 去掉PEM文件中的首尾标识，并解码为DER格式
        String publicKeyPEM = new String(keyBytes)
                .replace("-----BEGIN PUBLIC KEY-----", "")
                .replace("-----END PUBLIC KEY-----", "")
                .replaceAll("\\s", "");

        byte[] decodedBytes = Base64.getDecoder().decode(publicKeyPEM);

        // 使用X509EncodedKeySpec加载DER格式的公钥
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(decodedBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePublic(keySpec);
    }

    public static PrivateKey getPrivateKey(InputStream inputStream) throws Exception {
        // 从InputStream读取PEM格式的私钥文件内容
        byte[] keyBytes = readAllBytes(inputStream);

        // 去掉PEM文件中的首尾标识，并解码为DER格式
        String privateKeyPEM = new String(keyBytes)
                .replace("-----BEGIN PRIVATE KEY-----", "")
                .replace("-----END PRIVATE KEY-----", "")
                .replaceAll("\\s", "");

        byte[] decodedBytes = Base64.getDecoder().decode(privateKeyPEM);

        // 使用PKCS8EncodedKeySpec加载DER格式的私钥
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decodedBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePrivate(keySpec);
    }


    private static byte[] readAllBytes(InputStream inputStream) throws IOException {
        byte[] buffer = new byte[1024];
        int bytesRead;
        ByteArrayOutputStream output = new ByteArrayOutputStream();

        while ((bytesRead = inputStream.read(buffer)) != -1) {
            output.write(buffer, 0, bytesRead);
        }
        return output.toByteArray();
    }
    /*public static PrivateKey getPrivateKey(String filePath) throws Exception {
        ClassLoader classLoader = RsaUtils.class.getClassLoader();
        InputStream inputStream = classLoader.getResourceAsStream(filePath);

        if (inputStream == null) {
            throw new FileNotFoundException("File not found: " + filePath);
        }
        byte[] bytes = readFile(filePath);
        return getPrivateKey(bytes);
    }
    *//**
     * 获取公钥
     *
     * @param bytes 公钥的字节形式
     * @return
     * @throws Exception
     *//*
    public static PublicKey getPublicKey(byte[] bytes) {
        try {
            bytes = Base64.getDecoder().decode(bytes);
            X509EncodedKeySpec spec = new X509EncodedKeySpec(bytes);
            KeyFactory factory = KeyFactory.getInstance("RSA");
            return factory.generatePublic(spec);
        } catch (Exception e) {
            throw new RuntimeException("字节转换公钥对象失败！");
        }
    }
*/
    /**
     * 获取私钥
     *
     * @param bytes 私钥的字节形式
     * @return
     * @throws Exception
     */
    public static PrivateKey getPrivateKey(byte[] bytes) {
        try {
            bytes = Base64.getDecoder().decode(bytes);
            PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(bytes);
            KeyFactory factory = KeyFactory.getInstance("RSA");
            return factory.generatePrivate(spec);
        } catch (Exception e) {
            throw new RuntimeException("读取或转换私钥对象失败！", e);
        }
    }

    /**
     * 根据密文，生存rsa公钥和私钥,并写入指定文件
     *
     * @param publicKeyFilename  公钥文件路径
     * @param privateKeyFilename 私钥文件路径
     * @param secret             生成密钥的密文
     */
    public static void generateKey(String publicKeyFilename,
                                   String privateKeyFilename,
                                   String secret, int keySize) throws Exception {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        SecureRandom secureRandom = new SecureRandom(secret.getBytes());
        keyPairGenerator.initialize(Math.max(keySize, DEFAULT_KEY_SIZE), secureRandom);
        KeyPair keyPair = keyPairGenerator.genKeyPair();
        // 获取公钥并写出
        byte[] publicKeyBytes = keyPair.getPublic().getEncoded();


        publicKeyBytes = Base64.getEncoder().encode(publicKeyBytes);


        writeFile(publicKeyFilename, publicKeyBytes);
        // 获取私钥并写出
        byte[] privateKeyBytes = keyPair.getPrivate().getEncoded();
        privateKeyBytes = Base64.getEncoder().encode(privateKeyBytes);
        
        writeFile(privateKeyFilename, privateKeyBytes);
    }


    private static byte[] readFile(String filePath) throws Exception {
        try (InputStream inputStream = RsaUtils.class.getClassLoader().getResourceAsStream(filePath)) {
            if (inputStream == null) {
                throw new RuntimeException("找不到资源：" + filePath);
            }
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int length;
            while ((length = inputStream.read(buffer)) != -1) {
                baos.write(buffer, 0, length);
            }
            return baos.toByteArray();
        } catch (IOException e) {
            throw new RuntimeException("读取资源失败：" + filePath, e);
        }
    }

    /*private static byte[] readFile(String filePath) throws Exception {

        *//* try {
            return Files.readAllBytes(new File(filePath).toPath());
        } catch (IOException e) {
            throw new RuntimeException("读取密钥失败：" + filePath);
        }*//*
        try {
            // 使用类加载器获取资源流
            InputStream inputStream = RsaUtils.class.getClassLoader().getResourceAsStream(filePath);

            if (inputStream == null) {
                throw new RuntimeException("找不到密钥文件：" + filePath);
            }
            // 从输入流中读取字节数据
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int length;
            while ((length = inputStream.read(buffer)) != -1) {
                baos.write(buffer, 0, length);
            }
            return baos.toByteArray();
        } catch (IOException e) {
            throw new RuntimeException("读取密钥失败：" + filePath, e);
        }
    }
*/

    private static void writeFile(String destPath, byte[] bytes) throws IOException {
        System.out.println("2222222222");
        try {

            File dest = new File(destPath);
            System.out.println("1111111111");
            if (!dest.exists()) {
                System.out.println("33333333333");
                dest.createNewFile();
            }
            System.out.println("444444444444");
            Files.write(dest.toPath(), bytes);
        } catch (IOException e) {
            throw new RuntimeException("写出密钥失败：" + destPath);
        }
    }

    //修改自己的工作空间地址：itsource密钥可以随便写
    public static void main(String[] args) throws Exception {
        //1 生成秘钥对：公钥文件xxx_rsa.pub，私钥文件xxx_rsa.pri
        generateKey("H:\\PetHome\\PetHome\\PetHome_server\\src\\main\\resources\\auth_rsa.pub",
                "H:\\PetHome\\PetHome\\PetHome_server\\src\\main\\resources\\auth_rsa.pri", "itsource", 2048);

    }
}